package com.icetech.eom.controller.sys;

import com.google.common.collect.Lists;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.icetech.commonbase.ResultTools;
import com.icetech.commonbase.constants.CodeConstantsEnum;
import com.icetech.commonbase.domain.response.ObjectResponse;
import com.icetech.eom.common.annotation.SystemLog;
import com.icetech.eom.common.constant.CommonConstant;
import com.icetech.eom.common.constant.UserTypeEnum;
import com.icetech.eom.config.security.permission.MySecurityMetadataSource;
import com.icetech.eom.domain.sys.Permission;
import com.icetech.eom.domain.sys.RolePermission;
import com.icetech.eom.domain.sys.User;
import com.icetech.eom.service.sys.IPermissionService;
import com.icetech.eom.service.sys.IRolePermissionService;
import com.icetech.eom.service.utils.SecurityUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;


/**
 * @author wangzw
 */
@Slf4j
@RestController
@Api(description = "菜单/权限管理接口")
@RequestMapping("/permission")
@Transactional(rollbackFor = RuntimeException.class)
public class PermissionController {

    @Autowired
    private IPermissionService permissionService;

    @Autowired
    private IRolePermissionService rolePermissionService;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private SecurityUtil securityUtil;

    @Autowired
    private MySecurityMetadataSource mySecurityMetadataSource;

    @RequestMapping(value = "/getMenuList",method = RequestMethod.GET)
    @ApiOperation(value = "获取用户页面菜单数据")
    @SystemLog(description = "获取菜单列表")
    public ObjectResponse<List<Permission>> getAllMenuList(){

        List<Permission> list;
        // 读取缓存
        User u = securityUtil.getCurrUser();
        if (Objects.isNull(u)){
            return ResultTools.success(new ArrayList<>());
        }
        //如果当前用户是超级管理员,则拥有所有的权限
        String key = "permission::userMenuList:" + u.getId();
        String v = redisTemplate.opsForValue().get(key);
        if(StringUtils.isNotBlank(v)&&!v.equals("[]")){
            list = new Gson().fromJson(v, new TypeToken<List<Permission>>(){}.getType());
            return ResultTools.success(list);
        }
        if (u.getUserType().equals(UserTypeEnum.admin.getType())){
            //获取所有的权限
            list = permissionService.getAllPermission();
        }else {
            // 用户所有权限 已排序去重
            list = permissionService.findByUserId(u.getId());
        }

        List<Permission> menuList = new ArrayList<>();
        //筛选一级页面
        for(Permission p : list){
            if(CommonConstant.PERMISSION_PAGE.equals(p.getType())&&CommonConstant.LEVEL_ONE.equals(p.getLevel())){
                menuList.add(p);
            }
        }
        //筛选二级页面
        List<Permission> secondMenuList = new ArrayList<>();
        for(Permission p : list){
            if(CommonConstant.PERMISSION_PAGE.equals(p.getType())&&CommonConstant.LEVEL_TWO.equals(p.getLevel())){
                secondMenuList.add(p);
            }
        }
        //筛选二级页面拥有的按钮权限
        List<Permission> buttonPermissions = new ArrayList<>();
        for(Permission p : list){
            if(CommonConstant.PERMISSION_OPERATION.equals(p.getType())&&CommonConstant.LEVEL_THREE.equals(p.getLevel())){
                buttonPermissions.add(p);
            }
        }

        //匹配二级页面拥有权限
        for(Permission p : secondMenuList){
            List<String> permTypes = new ArrayList<>();
            for(Permission pe : buttonPermissions){
                if(p.getId().equals(pe.getParentId())){
                    permTypes.add(pe.getButtonType());
                }
            }
            p.setPermTypes(permTypes);
        }
        //匹配一级页面拥有二级页面
        for(Permission p : menuList){
            List<Permission> secondMenu = new ArrayList<>();
            for(Permission pe : secondMenuList){
                if(p.getId().equals(pe.getParentId())){
                    secondMenu.add(pe);
                }
            }
            p.setChildren(secondMenu);
        }

        // 缓存
        if (!CollectionUtils.isEmpty(menuList)){
            redisTemplate.opsForValue().set(key, new Gson().toJson(menuList));
        }
        return ResultTools.success(menuList);
    }

    @RequestMapping(value = "/getAllList",method = RequestMethod.GET)
    @ApiOperation(value = "获取权限菜单树")
    @SystemLog(description = "获取所有的权限菜单树")
    public ObjectResponse<List<Permission>> getAllList(){

        //一级
        List<Permission> list = permissionService.findByLevelOrderBySortOrder(CommonConstant.LEVEL_ONE);
        //二级
        for(Permission p1 : list){
            List<Permission> children1 = permissionService.findByParentIdOrderBySortOrder(p1.getId());
            p1.setChildren(children1);
            //三级
            for(Permission p2 : children1){
                List<Permission> children2 = permissionService.findByParentIdOrderBySortOrder(p2.getId());
                p2.setChildren(children2);
            }
        }
        return ResultTools.success(list);
    }

    @RequestMapping(value = "/getParent",method = RequestMethod.GET)
    @ApiOperation(value = "获取父级权限菜单树")
    public ObjectResponse<List<Permission>> getParent(){
        //一级
        List<Permission> one = permissionService.findByLevelOrderBySortOrder(CommonConstant.LEVEL_ONE);
        //二级
        List<Permission> two = permissionService.findByLevelOrderBySortOrder(CommonConstant.LEVEL_TWO);
        List<Permission> all = Lists.newArrayList();
        all.addAll(one);
        all.addAll(two);
        //添加一个空值的节点
        Permission permission = new Permission();
        permission.setName("顶级菜单");
        permission.setId(-1L);
        all.add(0,permission);
        return ResultTools.success(all);
    }

    @RequestMapping(value = "/add",method = RequestMethod.POST)
    @ApiOperation(value = "添加")
    @SystemLog(description = "添加菜单权限")
    public ObjectResponse<Permission> add(@RequestBody Permission permission){
        // 判断拦截请求的操作权限按钮名是否已存在
        if (permission.getType() == 0) {
            List<Permission> list = permissionService.findByTitle(permission.getTitle());
            if (list != null && list.size() > 0) {
                return ResultTools.fail(CodeConstantsEnum.ERROR_400.getCode(), "名称已经存在");
            }
            // 如果没有父id为一级
            if (permission.getParentId()==null || permission.getParentId() == -1){
                permission.setLevel(CommonConstant.LEVEL_ONE);
            }else {
                permission.setLevel(CommonConstant.LEVEL_TWO);
            }
        }

        if (permission.getType() == 1){
            List<Permission> list = permissionService.findByButtonType(permission.getButtonType());
            if (list != null && list.size() > 0) {
                return ResultTools.fail(CodeConstantsEnum.ERROR_400.getCode(), "权限标识已经存在");
            }
            permission.setLevel(CommonConstant.LEVEL_THREE);
        }
        permissionService.save(permission);
        //重新加载权限
        mySecurityMetadataSource.loadResourceDefine();
        //手动批量删除缓存
        Set<String> keys = redisTemplate.keys("userPermission:" + "*");
        redisTemplate.delete(keys);
        Set<String> keysUser = redisTemplate.keys("user:" + "*");
        redisTemplate.delete(keysUser);
        Set<String> keysUserMenu = redisTemplate.keys("permission::userMenuList:*");
        redisTemplate.delete(keysUserMenu);
        redisTemplate.delete("permission::allList");
        return ResultTools.success(null);
    }

    @RequestMapping(value = "/edit",method = RequestMethod.POST)
    @ApiOperation(value = "编辑")
    @SystemLog(description = "编辑菜单权限")
    public ObjectResponse<Permission> edit(@RequestBody Permission permission){

        // 判断拦截请求的操作权限按钮名是否已存在
        Permission p = permissionService.getById(permission.getId());
        if (permission.getType() == 0) {
            if(!p.getTitle().equals(permission.getTitle())){
                List<Permission> list = permissionService.findByTitle(permission.getTitle());
                if(list!=null&&list.size()>0){
                    return ResultTools.fail(CodeConstantsEnum.ERROR_400.getCode(),"名称已经存在");
                }
            }
            // 如果没有父id为一级
            if (permission.getParentId()==null || permission.getParentId() == -1){
                permission.setLevel(CommonConstant.LEVEL_ONE);
            }else {
                permission.setLevel(CommonConstant.LEVEL_TWO);
            }
        }
        if (permission.getType() == 1){
            if (!p.getButtonType().equals(permission.getButtonType())){
                List<Permission> list = permissionService.findByButtonType(permission.getButtonType());
                if (list != null && list.size() > 0) {
                    return ResultTools.fail(CodeConstantsEnum.ERROR_400.getCode(), "权限标识已经存在");
                }
            }
            permission.setLevel(CommonConstant.LEVEL_THREE);
        }
        permissionService.updateById(permission);
        //重新加载权限
        mySecurityMetadataSource.loadResourceDefine();
        //手动批量删除缓存
        Set<String> keys = redisTemplate.keys("userPermission:" + "*");
        redisTemplate.delete(keys);
        Set<String> keysUser = redisTemplate.keys("user:" + "*");
        redisTemplate.delete(keysUser);
        Set<String> keysUserMenu = redisTemplate.keys("permission::userMenuList:*");
        redisTemplate.delete(keysUserMenu);
        redisTemplate.delete("permission::allList");
        return ResultTools.success(null);
    }

    @RequestMapping(value = "/delByIds",method = RequestMethod.GET)
    @ApiOperation(value = "批量通过id删除")
    @SystemLog(description = "删除菜单")
    public ObjectResponse<Object> delByIds(@RequestParam("ids") List<Long> ids){

        for(Long id:ids){
            List<RolePermission> list = rolePermissionService.findByPermissionId(id);
            if(list!=null&&list.size()>0){
                return ResultTools.fail(CodeConstantsEnum.ERROR_400.getCode(),"删除失败，包含正被角色使用关联的菜单或权限");
            }
        }
        for(Long id:ids){
            permissionService.removeById(id);
        }
        //重新加载权限
        mySecurityMetadataSource.loadResourceDefine();
        //手动批量删除缓存
        Set<String> keys = redisTemplate.keys("userPermission:" + "*");
        redisTemplate.delete(keys);
        Set<String> keysUser = redisTemplate.keys("user:" + "*");
        redisTemplate.delete(keysUser);
        Set<String> keysUserMenu = redisTemplate.keys("permission::userMenuList:*");
        redisTemplate.delete(keysUserMenu);
        redisTemplate.delete("permission::allList");
        return ResultTools.success(null);
    }

    @RequestMapping(value = "/search",method = RequestMethod.GET)
    @ApiOperation(value = "搜索菜单")
    @SystemLog(description = "搜索菜单列表")
    public ObjectResponse<List<Permission>> searchPermissionList(@RequestParam String title){
        List<Permission> list = permissionService.findByTitleLikeOrderBySortOrder("%"+title+"%");
        return ResultTools.success(list);
    }

    @RequestMapping(value = "/get",method = RequestMethod.GET)
    @ApiOperation(value = "获取菜单")
    public ObjectResponse<List<Permission>> getById(@RequestParam Integer permissionId){
        Permission permission = permissionService.getById(permissionId);
        return ResultTools.success(permission);
    }
}
